package com.schoolCommunity.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.schoolCommunity.entity.Information;
import com.schoolCommunity.entity.Member;
import com.schoolCommunity.mapper.MemberMapper;
import com.schoolCommunity.service.MemberService;
import com.schoolCommunity.util.DeleteES;
import com.schoolCommunity.util.GetIpAddress;
import com.schoolCommunity.util.InsertES;
import com.schoolCommunity.util.UploadPicture;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author YTH
 * @since 2020-09-06
 */
@Service
public class MemberServiceImpl extends ServiceImpl<com.schoolCommunity.mapper.MemberMapper, Member> implements MemberService {

    static final String EmailSignIn = "EmailSignIn";

    static final String EmailGetPass = "EmailGetPass";

    Logger log = Logger.getLogger(MemberServiceImpl.class);


    @Resource
    private MemberMapper MemberMapper;
    @Autowired
    private com.schoolCommunity.util.CheckInsertMember CheckInsertMember;
    @Autowired
    private com.schoolCommunity.util.CheckLoginMember CheckLoginMember;
    @Autowired
    @Qualifier("MyLoginTemplate")
    private RedisTemplate redisTemplate;
    @Autowired
    private com.schoolCommunity.util.SendEmail SendEmail;
    @Autowired
    private com.schoolCommunity.util.CheckEmailPass CheckEmailPass;
    @Autowired
    private UploadPicture UploadPicture;
    @Autowired
    private GetIpAddress getIpAddress;
    @Autowired
    private InsertES insertES;
    @Autowired
    private DeleteES deleteES;


    //注册，传入对象
    @Override
    public Information InsertMember(Member Member) {

        //定义返回对象
        Information<Member> information = new Information<>();
        //先校验验证码，会返回字符串结果
        //传入邮箱和验证码，组成唯一标识
//        String CheckEmailPassResult = CheckEmailPass.checkEmailSignIn(Member.getEmail(), EmailPass);

//        if(  CheckEmailPassResult.equals("验证码匹配")){   //先检验验证码，成功再校验数据

//            log.info("验证码匹配成功，开始检验数据");
        //校验数据，并过滤不安全数据
        String checkResult = CheckInsertMember.CheckInsertMember(Member);

        log.info("注册新建校验结果" + checkResult);

        if (checkResult.equals("数据安全")) {

            try {
                int insert = MemberMapper.insert(Member);

                if (insert != 0) {
                    long l = MemberMapper.GetLastId();
                    QueryWrapper queryWrapper = new QueryWrapper();
                    queryWrapper.eq("id", l);
                    Member = MemberMapper.selectOne(queryWrapper);
                    insertES.InsertMember(Member);
                    information.setCode(200).setMessage("角色注册成功");
                } else {
                    information.setCode(404).setMessage("用户注册失败");
                }
                redisTemplate.delete(Member.getEmail() + EmailSignIn);
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else {
            information.setCode(404).setMessage(checkResult);
        }
        return information;


//        }else{   //验证码不匹配，直接放回错误信息
//            information.setCode(404).setMessage(CheckEmailPassResult);
//            return information;
//        }

    }

    //单独校验邮箱验证码
    @Override
    public Information checkEmailSignIn(String email, String EmailSignIn) {

        //去空格
        email = email.replaceAll("//s", "");
        //定义返回对象
        Information<Member> information = new Information<>();

        //先校验验证码，会返回字符串结果
        //传入邮箱和验证码，组成唯一标识
        String CheckEmailPassResult = CheckEmailPass.checkEmailSignIn(email, EmailSignIn);

        if (CheckEmailPassResult.equals("验证码匹配")) {   //先检验验证码，成功再校验数据
            log.info("验证码匹配成功");
            information.setCode(200).setMessage(CheckEmailPassResult);
        } else {   //验证码不匹配，直接放回错误信息
            information.setCode(404).setMessage(CheckEmailPassResult);

        }
        return information;
    }

    //登录
    @Override
    public Information LoginMember(Member Member) {

        //校验数据
        String checkResult = CheckLoginMember.CheckLoginMember(Member);
        log.info("登录数据校验完成");
        log.info("登录数据校验的结果是" + checkResult);

        Information<Member> information = new Information<>();

        if (checkResult.equals("数据安全")) {

            Member member = null;
            try {

                //向数据库查询
                QueryWrapper<Member> QueryWrapper = new QueryWrapper();
                QueryWrapper.eq("email", Member.getEmail()).eq("password", Member.getPassword());
                QueryWrapper.select("family_name", "sex", "email", "grade", "college", "credit", "VIP", "nickname", "photo");
                member = MemberMapper.selectOne(QueryWrapper);


            } catch (Exception e) {
                log.info("数据库查询出现未知错误");
                information.setMessage("系统繁忙，稍后重试").setCode(404).setData(null);
                return information;
            }

            if (member != null && member.getCredit() > 1) {
                log.info(member.getNickname() + "角色登录成功了");
                information.setData(member).setMessage("角色登录成功").setCode(200);
            } else if (member != null && member.getCredit() <= 1) {
                information.setData(member).setMessage("该账号因为信用问题暂时无法登录，请联系管理员").setCode(200).setData(null);
            } else {
                information.setMessage("账号或密码错误").setCode(404);
            }
            return information;

        } else {

            information.setCode(404).setMessage(checkResult);

        }
        return information;


    }

    //发送注册用验证码
    @Override
    public Information SendSignInEmail(String email, String kaptcha, HttpServletRequest request) {

        email = email.replaceAll("\\s", ""); // 用””替换所有”\\s”：去除所有空格
        log.info("获取到的用于注册验证码是" + kaptcha);
        log.info("获取到的即将注册邮箱是是" + email);
        String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);

        String ipAddress = getIpAddress.getIpAddress(request);
        log.info("获取到的客户端IP是" + ipAddress);

        //暂时硬编码
        String CodeRedis = (String) redisTemplate.opsForValue().get("ipAddress+Constants.KAPTCHA_SESSION_KEY");
        log.info("后台获取redis存放的发送注册邮箱用的验证码是" + CodeRedis);
        log.info("后台生成的验证码是" + verifyCodeExpected);

        Information information = new Information();

        //校验图形验证码是否正确
        if (kaptcha == null || !kaptcha.equals(CodeRedis)) {
            log.info("验证码不一致");
            information.setCode(404).setMessage("验证码错误");
            return information;
        } else {
            log.info("验证码一致,继续下一步校验并发送邮箱数据");
        }


        //检验此邮箱是否已经被注册
        Set<String> allEmailsForSet = MemberMapper.getAllEmailsForSet();
        if (allEmailsForSet.contains(email)) {
            information.setMessage("此邮箱已经被注册").setCode(404);
            return information;
        }


        //检验redis是否已经存在该校验值
        Boolean aBoolean = redisTemplate.hasKey(email + EmailSignIn);
        System.out.println(email + EmailSignIn);
        System.out.println("判断的值是" + aBoolean);
        if (aBoolean) {  //redis已经存在该验证码
            System.out.println("检测到已经存在这个keys");
            information.setMessage("验证码已发送，请耐心等待。").setCode(200);
        } else {
            System.out.println("没有这个keys，开始重新写入发送");
            information.setMessage(SendEmail.sendSignInEmail(email)).setCode(200);
        }
        return information;


    }

    //发送找回密码用验证码
    @Override
    public Information SendGetPassEmail(String email, String kaptcha, HttpServletRequest request) {

        Information information = new Information();

        log.info("获取到用于找回密码的验证码是" + kaptcha);
        log.info("获取到的被找回邮箱是" + email);
        String verifyCodeExpected = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);

        String ipAddress = getIpAddress.getIpAddress(request);
        log.info("获取到的客户端IP是" + ipAddress);

        //获取暂时硬编码
        String CodeRedis = (String) redisTemplate.opsForValue().get("PassKaptcha");
        log.info("后台获取redis存放的发送修改密码用的验证码是" + CodeRedis);
        log.info("后台生成的验证码是" + verifyCodeExpected);


        //校验图形验证码是否正确
        if (kaptcha == null || !kaptcha.equals(CodeRedis)) {
            log.info("验证码不一致");
            information.setCode(404).setMessage("验证码错误");
            return information;
        } else {
            log.info("验证码一致,继续下一步校验并发送邮箱数据");
        }

        if (!email.matches("^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")) {
            information.setCode(404).setMessage("无用邮箱或邮箱格式不正确");
            return information;
        } else {

        }


        //获取数据库所有邮箱，是否有此邮箱
        Set<String> allEmailsForSet = MemberMapper.getAllEmailsForSet();
        if (allEmailsForSet.contains(email)) {  //存在此邮箱


            //检验redis是否已经存在该校验值
            log.info("检查redis的key有没有" + email + EmailGetPass);
            Boolean aBoolean = redisTemplate.hasKey(email + EmailGetPass);
            log.info("redis存在该key的判断是" + aBoolean);

            if (aBoolean) {  //redis已经存在该验证码
                log.info("检测到已经存在这个keys" + email + EmailGetPass);
                information.setMessage("找回密码的验证码已发送，请耐心等待。").setCode(200);

            } else {
                log.info("没有这个keys，开始重新写入发送");
                information.setMessage(SendEmail.sendGetPassEmail(email)).setCode(200);
            }
            return information;

        } else {
            information.setMessage("此邮箱还没有被注册，请先注册").setCode(404);
        }
        return information;

    }

    //检验密码验证码并修改密码
    @Override
    public Information checkAndChangePass(Member Member, String EmailGetPass) {

        Information<Member> information = new Information<>();
        //先校验验证码
        String CheckEmailPassResult = CheckEmailPass.checkChangePass(Member.getEmail(), EmailGetPass);

        if (CheckEmailPassResult.equals("验证码匹配")) {   //先检验验证码，成功再校验数据

            if (Member.getPassword().length() > 16) { //密码过长

                information.setMessage("密码长度不能超过16个字符").setCode(404);

            } else {  //验证码与数据均正确，写入新密码

                //确保数据安全，清空其他数据
                Member.setSex(null).setNickname(null).setGrade(null).setGrade(null).setId(null).setFamilyName(null).setCredit(null).setPhoto(null).setCollege(null).setVip(null);

                QueryWrapper QueryWrapper = new QueryWrapper();
                QueryWrapper.eq("email", Member.getEmail());
                int update = MemberMapper.update(Member, QueryWrapper);
                if (update != 0) {
                    information.setMessage("密码修改成功").setCode(200);
                } else {
                    information.setMessage("密码修改失败，请稍后尝试").setCode(404);
                }

            }
            return information;


        } else {   //验证码不匹配，直接返回错误信息
            information.setCode(404).setMessage(CheckEmailPassResult);
        }
        return information;


    }

    //上传图片
    @Override
    public Information UploadPicture(MultipartFile file, long memberId) {

        Information information = new Information();


        //检查文件是否为空
        if (file.isEmpty()) {
            information.setMessage("文件为空").setCode(404);
            return information;
        }

        //上传图片
        String upload = UploadPicture.upload(file, memberId);

        if (upload.equals("上传失败")) {
            information.setCode(404).setMessage("图片上传失败");
        } else {
            log.info("图片上传成功" + upload + "如果原来有文件，开始删除");

            QueryWrapper QueryWrapper = new QueryWrapper();
            QueryWrapper.eq("id", memberId);
            QueryWrapper.select("photo");

            String dd = MemberMapper.selectOne(QueryWrapper).getPhoto();

            //删除前端资源文件
            String imgurl ="E:/项目/学校社区/schoolCommunityVue/src/schoolCommunityPicture/picture/"+dd;
            System.out.println("需要删除的图片路径是："+imgurl);
            File oldPictrue = new File(imgurl);
            if (oldPictrue.exists() && !"E:/项目/学校社区/schoolCommunityVue/src/schoolCommunityPicture/picture/default.jpg".equals(imgurl)) {
                log.info("原来有旧文件，执行删除");
                oldPictrue.delete();
            } else {
                log.info("原来前端没有旧文件");
            }

            //删除后端资源文件
            String BackImgurl ="E:/项目/学校社区/vue-admin-template/src/views/schoolCommunityPicture/picture/"+dd;
            System.out.println("需要删除的后端图片路径是："+BackImgurl);
            File oldBackPictrue = new File(BackImgurl);
            if (oldBackPictrue.exists() && !"E:/项目/学校社区/vue-admin-template/src/views/schoolCommunityPicture/picture/default.jpg".equals(BackImgurl)) {
                log.info("原来有旧文件，执行删除");
                oldBackPictrue.delete();
            } else {
                log.info("原来后端没有旧文件");
            }


            int update = MemberMapper.update(new Member().setPhoto(upload), QueryWrapper);

            if (update != 0) {
                information.setMessage("图片写入成功").setCode(200);
            } else {
                information.setCode(404).setMessage("图片写入失败");
            }
        }
        return information;

    }

    //删除图片
    @Override
    public Information DeletePicture(long memberId) {

        Information information = new Information();
        Member Member = new Member();
        //删除改为默认图片
        Member.setPhoto("default.jpg");


        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("id", memberId);


        log.info("先删除文件夹中的文件");
        String dd = MemberMapper.selectOne(queryWrapper).getPhoto();
        //删除前端
        String imgurl ="E:/项目/学校社区/schoolCommunityVue/src/schoolCommunityPicture/picture/"+dd;
        System.out.println("需要删除的图片路径是："+imgurl);
        File oldPictrue = new File(imgurl);
        if (oldPictrue.exists() && !"E:/项目/学校社区/schoolCommunityVue/src/schoolCommunityPicture/picture/default.jpg".equals(imgurl)) {
            log.info("原来有旧文件，执行删除");
            oldPictrue.delete();
        } else {
            log.info("原来没有旧文件");
        }

        //删除后端资源文件
        String BackImgurl ="E:/项目/学校社区/vue-admin-template/src/views/schoolCommunityPicture/picture/"+dd;
        System.out.println("需要删除的后端图片路径是："+BackImgurl);
        File oldBackPictrue = new File(BackImgurl);
        if (oldBackPictrue.exists() && !"E:/项目/学校社区/vue-admin-template/src/views/schoolCommunityPicture/picture/default.jpg".equals(BackImgurl)) {
            log.info("原来有旧文件，执行删除");
            oldBackPictrue.delete();
        } else {
            log.info("原来后端没有旧文件");
        }

        log.info("数据库删除数据");
        int update = MemberMapper.update(Member, queryWrapper);
        if (update != 0) {
            information.setCode(200).setMessage("图片删除成功");
        } else {
            information.setMessage("图片删除失败").setCode(404);
        }

        return information;
    }

    @Override
    public Information DeleteMember(long memberId) throws IOException {
        int i = MemberMapper.deleteById(memberId);
        deleteES.DeleteESMember(memberId);
        Information information = new Information();
        information.setCode(200).setMessage("有" + i + "位用户被删除");
        return information;
    }

    @Override
    public Information UpdateMemberCredit(long memberId, int creditNumber) {

        Information information = new Information();

        if (creditNumber > 5 || creditNumber < 1) {
            information.setMessage("用户信用的等级最高为5，最低为0");
        } else {

            QueryWrapper QueryWrapper = new QueryWrapper();
            QueryWrapper.eq("id", memberId);

            int update = MemberMapper.update(new Member().setCredit(creditNumber), QueryWrapper);
            if (update != 0) {
                information.setMessage("有" + update + "条数据修改成功").setCode(200);
            } else {
                information.setCode(404).setMessage("修改失败，没有数据被修改");
            }


        }
        return information;
    }

    @Override
    public Information GetAllMember() {

        Information information = new Information();

        List<Member> members = MemberMapper.selectList(null);

        information.setCode(200).setMessage("获取所有数据成功").setData(members);
        return information;
    }


}
